// MAIN.JS
/* global $ */
let board = [];
let score = 0;
let hasConflicted = [];
let i;
let j;
$(document).ready(function(){
  newgame();
});

function newgame(){
  // 初始化棋盘格
  init();
  // 在随机两个格子生成数字
  generateOneNumber();
  generateOneNumber();
  //清除gameover界面
  $('.gameover-box').remove();
}

function init(){
  
  for(i = 0; i < 4; i++){
    for(j = 0; j <4; j++){
      const gridCell = $("#grid-cell-" + i + "-" + j);
      gridCell.css('top',getPosTop(i,j));
      gridCell.css('left',getPosLeft(i,j));
    }
  }
  for(i = 0; i < 4; i++){
    board[i] = [];
    hasConflicted[i] = [];
    for(j = 0; j < 4; j++)
      board[i][j] = 0;
    hasConflicted[i][j] = false;
  }
  score = 0;
  updateBoardView();
  updateScore(0);
}

function updateBoardView() {
  $(".number-cell").remove();
  
  for( i = 0 ; i < 4; i++)
    for( j = 0; j <4; j++){
      $("#grid-container").append('<div class="number-cell" id="number-cell-'+i+'-'+j+'"></div>');
      const theNumberCell = $('#number-cell-' + i + '-' + j);
      
      if(board[i][j] === 0){
        theNumberCell.css('width','0px');
        theNumberCell.css('height','0px');
        theNumberCell.css('top',getPosTop(i,j)+50);
        theNumberCell.css('left',getPosLeft(i,j)+50);
      }else{
        theNumberCell.css('width','100px');
        theNumberCell.css('height','100px');
        theNumberCell.css('top',getPosTop(i,j));
        theNumberCell.css('left',getPosLeft(i,j));
        theNumberCell.css('background-color',getNumberBackgroundColor(board[i][j]));
        theNumberCell.css('color',getNumberColor(board[i][j]));
        theNumberCell.text(board[i][j]);
      }
      hasConflicted[i][j] = false;
    }
}

function generateOneNumber(){
  if(nospace(board)){
    return false;
  }
  //随机一个位置
  // parseInt(Math.floor(Math.random() * 4));
  let randx = Math.floor(Math.random() * 4);
  let randy = Math.floor(Math.random() * 4);
  let times = 0;
  while(times < 50){
    if(board[randx][randy] === 0){
      break;
    }
    randx = Math.floor(Math.random() * 4);
    randy = Math.floor(Math.random() * 4);
    times++
  }
  if(times === 50){
    for( i = 0; i < 4; i++){
      for(j =0; j < 4; j++){
        if(board[i][j] === 0){
          randx = i;
          randy = j;
        }
      }
    }
  }
  //随机一个数字
  const randNumber = Math.random()<0.5?2:4;
  //在随机位置显示随机数字
  board[randx][randy] = randNumber;
  showNumberWithAnimation(randx,randy,randNumber);
  
  return true;
}

$(document).keydown(function(event){
  switch(event.keyCode){
    case 37 : //left
      
      if(moveLeft()){
        setTimeout("generateOneNumber()",210);
        setTimeout("isgameover()",300);
      }
      break;
    case 38 : //up
      event.preventDefault();//取消方向键控制滚动条
      if(moveUp()){
        setTimeout("generateOneNumber()",210);
        setTimeout("isgameover()",300);
      }
      break;
    case 39 : //right
      if(moveRight()){
        setTimeout("generateOneNumber()",210);
        setTimeout("isgameover()",300);
      }
      break;
    case 40 : //down
      event.preventDefault();
      if(moveDown()){
        setTimeout("generateOneNumber()",210);
        setTimeout("isgameover()",300);
      }
      break;
    default : //default
      break;
  }
});

function isgameover(){
  if(nospace(board) && noMove(board)){
    gameover();
  }
}

function gameover(){
  $("#grid-container").append('<div class="gameover-box"><p class="gameover-text">Game Over</p></div>');
}

function moveLeft(){
  if(!canMoveLeft(board)){
    return false;
  }
  for( i = 0; i < 4; i++ ){
    for( j = 1; j < 4; j++ ){
      if(board[i][j]!==0){
        for(let k = 0; k < j; k++ ){
          if(board[i][k] === 0 && noBlockHorizontal(i,k,j,board)){
            //only move
            showMoveAnimation(i,j,i,k);
            board[i][k] = board[i][j];
            board[i][j] = 0;
            
          }
          else if(board[i][k] === board[i][j] && noBlockHorizontal(i,k,j,board) && !hasConflicted[i][k]){
            //move and add
            showMoveAnimation(i,j,i,k);
            board[i][k] += board[i][j];
            board[i][j] = 0;
            //add score
            score += board[i][k];
            updateScore(score);
            hasConflicted[i][k] = true;
            
          }
        }
      }
    }
  }
  setTimeout("updateBoardView()",200);
  return true;
}

function moveRight(){
  if(!canMoveRight(board)){
    return false;
  }
  for(i = 0; i < 4; i++ ){
    for( j = 2; j >= 0; j-- ){
      if(board[i][j] !== 0){
        for(let k = 3; k > j; k-- ){
          if(board[i][k] === 0 && noBlockHorizontal(i,j,k,board)){
            //move
            showMoveAnimation(i,j,i,k);
            board[i][k] = board[i][j];
            board[i][j] = 0;
            
          }
          else if(board[i][k] === board[i][j] && noBlockHorizontal(i,j,k,board) && !hasConflicted[i][k]){
            //move and add
            showMoveAnimation(i,j,i,k);
            board[i][k] *= 2;
            board[i][j] = 0;
            //add score
            score += board[i][k];
            updateScore(score);
            hasConflicted[i][k] = true;
            
          }
        }
      }
    }
  }
  setTimeout("updateBoardView()",200);
  return true;
}

function moveUp(){
  if(!canMoveUp(board)){
    return false;
  }
  for( j = 0; j < 4; j++ ){
    for( i = 1; i < 4; i++ ){
      if(board[i][j] !== 0){
        for(let k = 0; k < i; k++ ){
          if(board[k][j] === 0 && noBlockVertical(j,k,i,board)){
            //move
            showMoveAnimation(i,j,k,j);
            board[k][j] = board[i][j];
            board[i][j] = 0;
            
          }
          else if(board[k][j] === board[i][j] && noBlockVertical(j,k,i,board) && !hasConflicted[k][j]){
            //move and add
            showMoveAnimation(i,j,k,j);
            board[k][j] *= 2;
            board[i][j] = 0;
            //add score
            score += board[k][j];
            updateScore(score);
            hasConflicted[k][j] = true;
            
          }
        }
      }
    }
  }
  setTimeout("updateBoardView()",200);
  return true;
}

function moveDown(){
  if( !canMoveDown( board ) )
    return false;
  
  //moveDown
  for(j = 0 ; j < 4 ; j ++ )
    for( i = 2 ; i >= 0 ; i -- ){
      if( board[i][j] !== 0 ){
        for(let k = 3 ; k > i ; k -- ){
          
          if( board[k][j] === 0 && noBlockVertical( j , i , k , board ) ){
            showMoveAnimation( i , j , k , j );
            board[k][j] = board[i][j];
            board[i][j] = 0;
            
          }
          else if( board[k][j] === board[i][j] && noBlockVertical( j , i , k , board ) && !hasConflicted[k][j]){
            showMoveAnimation( i , j , k , j );
            board[k][j] *= 2;
            board[i][j] = 0;
            //add score
            score += board[k][j];
            updateScore(score);
            hasConflicted[k][j] = true;
            
          }
        }
      }
    }
  
  setTimeout("updateBoardView()",200);
  return true;
}


// SUPPORT.JS
/*global $*/
function getPosLeft(i,j){
  return 20+j*120;
}
function getPosTop(i,j) {
  return 20+i*120;
}
function getNumberBackgroundColor(number) {
  switch (number) {
    case 2:return "#eee4da";
    case 4 :return "#ede0c8";
    case 8 :return "#f2b179";
    case 16 :return "#f59563";
    case 32 :return "#f67c5f";
    case 64 :return "#f65e3b";
    case 128 :return "#edcf72";
    case 256 :return "#edcc61";
    case 512 :return "#9c0";
    case 2048 :return "#09c";
    case 4096 :return "#a6c";
    case 8192 :return "#93c";
  }
  return "block"
}
function getNumberColor(number){
  if(number<=4)
    return "#776e65";
  
  return "white";
}
function nospace(board){
  for(let i = 0 ; i < 4; i++){
    for(let j = 0; j <4; j++)
      if(board[i][j] === 0){
        return false;
      }
  }
  return true;
}
function canMoveLeft(board) {
  for (let i=0;i<4;i++) {
    for (let j = 1; j < 4; j++) {
      if(board[i][j]!==0){
        if(board[i][j-1]===0||board[i][j-1]=== board[i][j]){
          return true;
        }
      }
    }
  }
  return false
}
function canMoveRight(board) {
  for (let i=0;i<4;i++) {
    for (let j = 2; j>=0; j--) {
      if(board[i][j]!==0){
        if(board[i][j+1]===0||board[i][j+1]=== board[i][j]){
          return true;
        }
      }
    }
  }
  return false
}
function canMoveUp(board) {
  for (let j=0;j<4;j++) {
    for (let i = 1; i< 4; i++) {
      if(board[i][j]!==0){
        if(board[i-1][j]===0||board[i-1][j]=== board[i][j]){
          return true;
        }
      }
    }
  }
  return false
}
function canMoveDown(board) {
  //error:(let j=1) T:let j=0;
  for (let j = 0; j < 4; j++) {
    for (let i=2;i>=0;i--) {
      if(board[i][j]!==0){
        if(board[i+1][j]===0||board[i+1][j]=== board[i][j]){
          return true;
        }
      }
    }
  }
  return false
}
// 水平线 下一步可进行即点到点之间无障碍也可以设计条件为i=col1
function noBlockHorizontal(row,col1,col2,board) {
  for (let i=col1+1;i<col2;i++){
    if (board[row][i]!==0)
      return false;
  }
  return  true;
}
function noBlockVertical( col , row1 , row2 , board ){
  for(let i=row1+1;i<row2;i++){
    if (board[i][col]!==0)
      return false
  }
  return true;
}
function noMove(){
  if( canMoveUp(board) || canMoveRight(board) || canMoveDown(board) || canMoveLeft(board)){
    return false;
  }
  return true;
}

function updateScore(score){
  $('#score').text(score);
}


//ANIMATION.JS
/*global $*/
// function  showNumberWithAnimation(i,j,randNumber) {
//   let numberCell=$('.number-cell-'+i+'-'+j);
//   numberCell.css('background-color',getNumberBackgroundColor(randNumber));
//   numberCell.css('color',getNumberColor(randNumber));
//   numberCell.text(randNumber);
//   numberCell.animate({
//     width:"100px",
//     height:"100px",
//     top:getPosTop(i,j),
//     left:getPosLeft(i,j)}, 50)
//
// }
// function showMoveAnimation(fromx,fromy,tox,toy){
//   let numberCell = $('#number-cell-' + fromx +'-'+fromy);
//   numberCell.animate({
//     top : getPosTop(tox,toy),
//     left : getPosLeft(tox,toy)
//   },200);
// }
/*global $*/
function showNumberWithAnimation(i,j,randNumber){
  var numberCell = $('#number-cell-'+i+'-'+j);
  
  numberCell.css('background-color',getNumberBackgroundColor(randNumber));
  numberCell.css('color',getNumberColor(randNumber));
  numberCell.text(randNumber);
  
  numberCell.animate({
    width:"100px",
    height:"100px",
    top:getPosTop(i,j),
    left:getPosLeft(i,j)
  },50);
}

function showMoveAnimation(fromx,fromy,tox,toy){
  var numberCell = $('#number-cell-' + fromx +'-'+fromy);
  numberCell.animate({
    top : getPosTop(tox,toy),
    left : getPosLeft(tox,toy)
  },200);
}